package cn.sh.ideal.yedis.core;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.sh.ideal.yedis.util.TimeUnit;
import redis.clients.jedis.Jedis;
import redis.clients.util.Pool;
/**
 * 'l' or 'r'开头的方法为list-列表操作<br>
 * 'h'开头的方法为map-哈希表操作<br>
 * 's'开头的方法为set-集合操作<br>
 * 'z'开头的方法为sortedset-有序结合操作<br>
 * @author wyy
 *
 * @param <V>
 */
@SuppressWarnings("unchecked")
public interface RedisOperation<V> {
	public static String STATUS_SUCCESS = "OK";
	/**
	 * 存储数据到缓存中，若key已存在则覆盖 
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public void set(final String key, final V value) ;

	/**
	 * 存储数据到缓存中，若key已存在则覆盖 ,并设置过期时间
	 *
	 * @param key
	 * @param value
	 * @param timeout
	 * @param unit
	 * @return
	 */
	public void set(final String key, final V value, final int timeout, final TimeUnit unit);

	/**
	 * 存储数据到缓存中，若key已存在则返回false且不设置值不存在则则设置值返回true
	 *
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setNx(final String key, final V value) ;

	/**
	 * 存储数据到缓存中.
	 *
	 * @param key
	 * @param value
	 * @param nxxx NX:当key不存在设值;XX：当key存在时设值
	 * @param timeout 超时时间
	 * @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds
	 * @return
	 */
	public boolean set(final String key, String value,final String nxxx, final long timeout, final String expx);
	
	/**
	 * 从缓存中根据key取得其String类型的值，如果key不存在则返回null
	 *
	 * @param key
	 * @return
	 */
	public V get(final String key) ;

	/**
	 * 从缓存中删除key
	 *
	 * @param key
	 * @return
	 */
	public void del(final String key) ;

	/**
	 * 向存于 key 的列表的头部插入所有指定的值。如果 key 不存在，那么会创建一个空的列表然后再进行 push 操作。 
	 * 
	 * @param key
	 * @param string
	 * @return 在 push 操作后的列表长度。
	 */
	public Long lpush(final String key,final V... values) ;

	/**
	 * 向存于 key 的列表的尾部插入所有指定的值。如果 key 不存在，那么会创建一个空的列表然后再进行 push 操作。 
	 * 
	 * @param key
	 * @param values
	 * @return 在 push 操作后的列表长度。
	 */
	public Long rpush(final String key,final V... values);

	/**
	 * 移除并且返回 key 对应的 list 的第一个元素。
	 *
	 * @param key
	 * @return 返回第一个元素的值，或者当 key 不存在时返回 null。
	 */
	public V lpop(final String key);

	/**
	 * 移除并返回存于 key 的 list 的最后一个元素。
	 *
	 * @param key
	 * @return 最后一个元素的值，或者当 key 不存在的时候返回 null。
	 */
	public V rpop(final String key) ;
	
	/**
	 * 当列表不为空时返回
	 *
	 * @param timeout 超时时间（秒），0代表无限阻塞
	 * @param key
	 * @return 列表的key
	 */
	public V blpop(final int timeout,final String key);
	
	/**
	 * 当列表不为空时返回
	 *
	 * @param timeout 超时时间（秒），0代表无限阻塞
	 * @param key
	 * @return 列表的key
	 */
	public V brpop(final int timeout,final String key);

	/**
	 * 返回存储在 key 里的list的长度。 如果 key 不存在，那么就被看作是空list，并且返回长度为 0。 
	 *
	 * @param key
	 * @return key对应的list的长度。
	 */
	public Long llen(final String key) ;


	/**
	 * 返回存储在 key 的列表里所有元素
	 *
	 * @param key
	 * @return 列表元素。
	 */
	public List<V> lrange(final String key);

	/**
	 * 返回存储在 key 的列表里指定范围内的元素。 start 和 end
	 *
	 * @param key
	 * @param start
	 * @param end
	 * @return 指定范围里的列表元素。
	 */
	public List<V> lrange(final String key, final Long start, final Long end);

	/**
	 * 返回列表里的元素的索引 index 存储在 key 里面。
	 *
	 * @param key
	 * @param index
	 * @return 请求的对应元素，或者当 index 超过范围的时候返回 null。
	 */
	public V lindex(final String key,final Long index);

	/**
	 * 从存于 key 的列表里移除值为 value 的元素。 
	 * 
	 * @param key
	 * @param value
	 * @return 返回删除的个数
	 */
	public Long lrem(final String key,final V value) ;
	
	/**
	 * 移除指定范围外的元素
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public String ltrim(final String key,long start,long end);

	/**
	 * 设置hash表里field字段的值为value。如果key不存在，则创建一个新的hash表
	 * 
	 * @param key
	 * @param field
	 * @param value
	 * @return 如果该字段已经存在，那么将会更新该字段的值，返回0.如果字段不存在，则新创建一个并且返回1.
	 */
	public Long hset(final String key,final String field,final V value) ;

	/**
	 * 当字段不存在时，才进行set。
	 *
	 * @param key
	 * @param field
	 * @param value
	 * @return 如果该字段已经存在，则返回0.若字段不存在，则创建后set，返回1.
	 */
	public Long hsetnx(final String key,final String field,final V value) ;

	/**
	 * 如果该key对应的值是一个Hash表，则返回对应字段的值。 如果不存在该字段，或者key不存在，则返回一个null。
	 *
	 * @param key
	 * @param field
	 * @return
	 */
	public V hget(final String key,final String field);

	/**
	 * 设置多个字段和值，如果字段存在，则覆盖。
	 *
	 * @param key
	 * @param hash
	 * @return 设置成功返回OK，设置不成功则返回EXCEPTION
	 */
	public String hmset(final String key,final Map<String,V> hash);

	/**
	 * 在hash中获取多个字段的值，若字段不存在，则返回空集合。
	 *
	 * @param key
	 * @param fields
	 * @return 按顺序返回多个字段的值。
	 */
	public List<V> hmget(final String key, final String... fields);

	/**
	 * 判断hash中指定字段是否存在
	 *
	 * @param key
	 * @param field
	 * @return 若存在返回1，若不存在返回0
	 */
	public Boolean hexists(final String key, final String field) ;

	/**
	 * 删除hash中指定字段
	 *
	 * @param key
	 * @param field
	 * @return 删除成功返回1， 删除不成功返回0
	 */
	public Long hdel(final String key, final String... field) ;

	/**
	 * 返回 key 指定的哈希集包含的字段的数量
	 *
	 * @param key
	 * @return 哈希集中字段的数量，当 key 指定的哈希集不存在时返回 0
	 */
	public Long hlen(final String key) ;

	/**
	 * 返回 key 指定的哈希集中所有字段的名字。
	 *
	 * @param key
	 * @return 哈希集中的字段列表，当 key 指定的哈希集不存在时返回空列表。
	 */
	public Set<String> hkeys(final String key);

	/**
	 * 返回 key 指定的哈希集中所有字段的值。
	 *
	 * @param key
	 * @return 哈希集中的值的列表，当 key 指定的哈希集不存在时返回空列表。
	 */
	public List<V> hvals(final String key);

	/**
	 * 返回 key 指定的哈希集中所有的字段和值
	 *
	 * @param key
	 * @return 返回 key 指定的哈希集中所有的字段和值,若key不存在返回空map。
	 */
	public Map<String, V> hgetAll(final String key);

	/**
	 * 添加一个或多个指定的member元素到集合的 key中.指定的一个或者多个元素member 如果已经在集合key中存在则忽略.如果集合key
	 * 不存在，则新建集合key,并添加member元素到集合key中.
	 * 
	 * 如果key 的类型不是集合则返回错误.
	 *
	 * @param key
	 * @param member
	 * @return 返回新成功添加到集合里元素的数量，不包括已经存在于集合中的元素.
	 */
	public Long sadd(final String key, final V... member);
	/**
	 * 返回key集合所有的元素.
	 * 
	 * 该命令的作用与使用一个参数的SINTER 命令作用相同.
	 *
	 * @param key
	 * @return 集合中的所有元素.
	 */
	public Set<V> smembers(final String key);
	/**
	 * 在key集合中移除指定的元素. 如果指定的元素不是key集合中的元素则忽略 如果key集合不存在则被视为一个空的集合，该命令返回0.
	 * 
	 * 如果key的类型不是一个集合,则返回错误.
	 *
	 * @param key
	 * @param member
	 * @return 从集合中移除元素的个数，不包括不存在的成员.
	 */
	public Long srem(final String key, final V... member);

	/**
	 * 移除并返回一个集合中的随机元素
	 * 
	 * 该命令与 SRANDMEMBER相似,不同的是srandmember命令返回一个随机元素但是不移除.
	 *
	 * @param key
	 * @return 被移除的元素, 当key不存在的时候返回 null .
	 */
	public V spop(final String key) ;

	/**
	 * 移除并返回多个集合中的随机元素
	 * 
	 * @param key
	 * @param count
	 * @return 被移除的元素, 当key不存在的时候值为 空集合 .
	 */
	public Set<V> spop(final String key, final Long count);

	/**
	 * 返回集合存储的key的基数 (集合元素的数量).
	 *
	 * @param key
	 * @return 集合的基数(元素的数量),如果key不存在,则返回 0.
	 */
	public Long scard(final String key) ;

	/**
	 * 返回成员 member 是否是存储的集合 key的成员.
	 *
	 * @param key
	 * @param member
	 * @return 如果member元素是集合key的成员，则返回1.如果member元素不是key的成员，或者集合key不存在，则返回0
	 */
	public Boolean sismember(final String key, final V member);
	
	/**
	 * 将指定成员 member 元素从 source 集合移动到 destination 集合。
	 * @param source
	 * @param dest
	 * @param member
	 */
	public Long smove(final String source,String dest,V member);

	/**
	 * 该命令添加指定的成员到key对应的有序集合中，每个成员都有一个分数。你可以指定多个分数/成员组合。
	 * 分数的值必须是一个表示数字的字符串，并且可以是double类型的浮点数。
	 *
	 * @param key
	 * @param score
	 * @param member
	 * @return 返回添加到有序集合中元素的个数，不包括那种已经存在只是更新分数的元素。
	 */
	public Long zadd(final String key, final double score, final V member);

	/**
	 * 返回有序集key中，指定区间内的成员。其中成员按score值递增(从小到大)来排序。具有相同score值的成员按字典序来排列。
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return 指定范围的元素列表
	 */
	public List<V> zrange(final String key, final Long start, final Long end);

	/**
	 * 从集合中删除指定member元素，当key存在，但是其不是有序集合类型，就返回一个错误。
	 *
	 * @param key
	 * @param member
	 * @return 返回的是从有序集合中删除的成员个数，不包括不存在的成员。
	 */
	public Long zrem(final String key, final V... member);

	/**
	 * 为有序集key的成员member的score值加上增量increment。
	 * @param key
	 * @param score
	 * @param member
	 * @return member成员的新score值.
	 */
	public Double zincrby(final String key, final double score, final V member) ;

	/**
	 * 返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。
	 *
	 * @param key
	 * @param member
	 * @return 如果member是有序集key的成员，返回member的排名的整数。 如果member不是有序集key的成员，返回 null。
	 */
	public Long zrank(final String key, final V member) ;

	/**
	 * 返回有序集key中成员member的排名，其中有序集成员按score值从大到小排列。
	 * @param key
	 * @param member
	 * @return 如果member是有序集key的成员，返回member的排名。整型数字。 如果member不是有序集key的成员，返回null
	 */
	public Long zrevrank(final String key, final V member) ;

	/**
	 * 返回有序集key中，指定区间内的成员。其中成员的位置按score值递减(从大到小)来排列。
	 *
	 * @param key
	 * @param start
	 * @param end
	 * @return 指定范围的元素列表(可选是否含有分数)。
	 */
	public List<V> zrevrange(final String key, final Long start, final Long end);

	/**
	 * 返回key的有序集元素个数。
	 *
	 * @param key
	 * @return key存在的时候，返回有序集的元素个数，否则返回0。
	 */
	public Long zcard(final String key) ;

	/**
	 * 返回有序集key中，成员member的score值。
	 * 
	 * 如果member元素不是有序集key的成员，或key不存在，返回null。
	 *
	 * @param key
	 * @param member
	 * @return member成员的score值（double型浮点数）
	 */
	public Double zscore(final String key, final V member) ;

	/**
	 * 返回有序集key中，score值在min和max之间(默认包括score值等于min或max)的成员。
	 *
	 * @param key
	 * @param min
	 * @param max
	 * @return 指定分数范围的元素个数。
	 */
	public Long zcount(final String key, final double min, final double max);

	/**
	 * 返回key的有序集合中的分数在min和max之间的所有元素（包括分数等于max或者min的元素）。元素被认为是从低分到高分排序的。
	 * 具有相同分数的元素按字典序排列
	 *
	 * @param key
	 * @param min
	 * @param max
	 * @return 指定分数范围的元素列表
	 */
	public List<V> zrangeByScore(final String key, final double min, final double max);

	/**
	 * 机制与zrangeByScore一样，只是返回结果为降序排序。
	 *
	 * @param key
	 * @param max
	 * @param min
	 * @return
	 */
	public List<V> zrevrangeByScore(final String key, final double max, final double min);

	/**
	 * 移除有序集key中，指定排名(rank)区间内的所有成员。下标参数start和stop都以0为底，0处是分数最小的那个元素。这些索引也可是负数，
	 * 表示位移从最高分处开始数。例如，-1是分数最高的元素，-2是分数第二高的，依次类推。
	 *
	 * @param key
	 * @param start
	 * @param end
	 * @return 被移除成员的数量。
	 */
	public Long zremrangeByRank(final String key, final Long start, final Long end);

	/**
	 * 移除有序集key中，所有score值介于min和max之间(包括等于min或max)的成员。
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return 删除的元素的个数
	 */
	public Long zremrangeByScore(final String key, final double start, final double end) ;

	/**
	 * 设置key的过期时间
	 * @param key
	 * @param timeout
	 * @param unit
	 */
	public void expire(final String key, final int timeout,final TimeUnit unit);

	/**
	 * 判断是否存在key
	 * @param key
	 * @return
	 */
	public boolean exists(final String key) ;

	/**
	 * 返回一个key还能活多久，单位为秒
	 *
	 * @param key
	 * @return 如果该key本来并没有设置过期时间，则返回-1，如果该key不存在，则返回-2
	 */
	public Long ttl(final String key) ;

	/**
	 * 根据表达式pattern模糊匹配key
	 * 
	 * @param pattern
	 * @return 
	 */
	public Set<String> keys(final String pattern);
	
	/**
	 * 将指定key的值减少某个值
	 *
	 * @param key
	 * @param integer
	 * @return 返回减少后的新值
	 */
	public Long decrBy(final String key,final Long integer) ;

	/**
	 * 将指定Key的值减少1
	 *
	 * @param key
	 * @return 返回减少后的新值
	 */
	public Long decr(final String key) ;
	
	/**
	 * 将指定的key的值增加指定的值
	 *
	 * @param key
	 * @param integer
	 * @return 返回增加后的新值
	 */
	public Long incrBy(final String key, final Long integer) ;

	/**
	 * 将指定的key的值增加1
	 *
	 * @param key
	 * @return 返回增加后的新值
	 */
	public Long incr(final String key) ;
	
	/**
	 * 获取计数器的值
	 *
	 * @param key
	 * @return 返回计数器的当前值
	 */
	public Long counter(final String key) ;

	/**
	 * 向指定渠道发布消息
	 *
	 * @param key
	 * @return 返回增加后的新值
	 */
	public Long publish(final String channel,final V message);

	/**
	 * 订阅某渠道消息
	 * 
	 * @param subcriber
	 * @param channel
	 */
	public void subcribe(final Subcriber<V> subcriber,final String channel,Pool<Jedis> pool);
	
	/**
	 * 取消订阅某渠道消息
	 * 
	 * @param subcriber
	 * @param channel
	 */
	public void unsubcribe(Subcriber<V> subcriber);

	/**
	 * 批量添加数据
	 * @param hash
	 */
	public void pipelineSet(final Map<String,V> hash) ;

	/**
	 * 批量取值
	 * @param keys
	 * @return
	 */
	public List<V> pipelineGet(final Collection<String> keys);

	/**
	 * 批量删除
	 * @param keys
	 * @return
	 */
	public void pipelineDel(final Collection<String> keys);
	
	/**
	 * 批量lpush
	 * @param keys
	 * @return
	 */
	public void pipelineRpush(final Map<String,V> values);
}
